import LiabilityAPI from '@/api/Liability';
import {
  Box,
  ClickModal,
  FieldCols,
  FormSection,
  Icon,
  PopoverConfirm,
  useCall,
  useFormValue,
  useReq,
  useSimpleMemo,
  useToggle,
} from '@/components';
import Expandable, { useExpandable } from '@/components/Expandable';
import { SelectLiability } from '@/pages/components';
import { arrayUnique, forkHandler, optionsToMap } from '@/utils';
import { catchAndScrollFor, set } from '@/utils/fp';
import { Button, Col, Form, Row, Space, Switch } from 'antd';
import clsx from 'clsx';
import * as PropTypes from 'prop-types';
import React, { useContext, useEffect, useState } from 'react';
import { Context, createDutyItem } from '.';
import styles from '../inedx.less';
import * as FIELDS from './FIELDS';

const getAllRuleValues = (nextRule, ruleCode = 'deductible', excludeIndex = -1) =>
  (nextRule ?? []).reduce(
    (ret, item, index) => [...ret, ...(ruleCode === item.ruleCode && excludeIndex !== index ? item.ruleValue : [])],
    [],
  );

export const getAllDutyCodes = (nextRule) =>
  arrayUnique(
    nextRule?.reduce((ret, item) => [...ret, ...item?.ruleSentence?.map((i) => i.dutyCode)], []).filter(Boolean) ?? [],
  );

function ExpandableAttributeItem(props) {
  const { title, expandedTitle, collapsedTitle, children } = props;
  const { expanded } = useExpandable();

  return (
    <div className={clsx(styles.attrLiabilityItem, styles.dutyRule, { [styles.collapsed]: !expanded })}>
      <div className={styles.delLine}>{title ?? (expanded ? expandedTitle : collapsedTitle)}</div>
      <Expandable.Content>{children}</Expandable.Content>
    </div>
  );
}

function NextRuleValue({ name }) {
  const { form } = useContext(Context);
  const ruleValue = useFormValue(form, ['duty', 'nextRule', name, 'ruleValue']) ?? [];
  const ruleCode = useFormValue(form, ['duty', 'nextRule', name, 'ruleCode']);
  const ruleName = useFormValue(form, ['duty', ruleCode, 'name']);

  return (
    <Box flex='inline' px={1}>
      ({ruleName}: {ruleValue.join(', ')})
    </Box>
  );
}

function DutyRuleTitle({ name, index, add, removeRule }) {
  const { expanded, toggle } = useExpandable();
  const title = (
    <div className={styles.title}>
      责任规则
      <NextRuleValue name={name} />
    </div>
  );

  const onRemove = useCall(removeRule, index);
  const onAdd = useCall(([liabilityItem]) => add(createDutyItem(liabilityItem)));

  if (expanded) {
    return (
      <Box grow>
        <Box flex jus='between' ali='center'>
          <Space>
            {title}
            <DutyRuleModal index={index}>
              <Button size='small'>修改规则</Button>
            </DutyRuleModal>
            <SelectLiability onOk={onAdd}>
              <Button size='small'>添加责任</Button>
            </SelectLiability>
          </Space>
          <Box grow />
          <Space>
            <PopoverConfirm content='确认删除此规则吗?' onOk={onRemove}>
              <Button size='small' className={styles.delBtn} type='link'>
                删除
              </Button>
            </PopoverConfirm>
            <Button size='small' type='link' onClick={toggle}>
              收起
            </Button>
          </Space>
        </Box>
      </Box>
    );
  }

  return (
    <>
      {title}
      <Box grow />
      <Button size='small' type='link' onClick={toggle}>
        展开
      </Button>
    </>
  );
}

function useLiabilityMap() {
  const xhr = useReq(LiabilityAPI.findByPage);
  xhr.startOnce({});

  return useSimpleMemo(optionsToMap(xhr.result?.data?.records ?? [], 'liabilityName', 'liabilityCode'));
}

export function DutyFormulaList() {
  const { form } = useContext(Context);
  const dutyCodes = useFormValue(form, ['duty', 'nextRule'], getAllDutyCodes);
  const liabilityMap = useLiabilityMap();
  const fields = useSimpleMemo(
    dutyCodes.map((dutyCode) => FIELDS.dutyFormula(dutyCode, `${liabilityMap?.[dutyCode] ?? ''}费率`)),
  );

  if (!dutyCodes?.length) return null;

  return (
    <FormSection title='保障责任费率'>
      <FieldCols form={form} fields={fields} />
    </FormSection>
  );
}

/** 责任列表 */

function DutyFields() {
  const { form } = useContext(Context);
  const show = useFormValue(form, ['productAddVo', 'productAttrVo', 'productCategory'], (v) => v === 'MC');
  const shouldDefaultOpen = useFormValue(form, 'duty', (v) => !!v?.dutyCode || v?.nextRule?.length > 0);
  const rules = useFormValue(form, ['duty', 'rules']);

  const [defaultOpen, setDefault] = useState(false);
  const updateDefaultOpen = useCall(() => {
    setDefault(shouldDefaultOpen);
  });
  useEffect(() => {
    setTimeout(updateDefaultOpen);
  }, [show]);
  const [enabled, toggle] = useToggle(defaultOpen);

  if (!show) return null;

  let content = null;
  let formula = null;

  if (enabled) {
    content = (
      <>
        <FieldCols fields={FIELDS.duty} form={form} />
        {rules?.map((ruleName) => (
          <FieldCols key={ruleName} fields={FIELDS.dutyRule(ruleName, ['duty'])} form={form} />
        )) ?? null}

        <Form.List name={['duty', 'nextRule']}>
          {(nextRuleFields, { add: addRule, remove: removeRule }) => {
            return (
              <Col xs={24}>
                <div>
                  <DutyRuleModal onOk={addRule}>
                    <Button icon={<Icon type='plus' />}>添加责任规则</Button>
                  </DutyRuleModal>
                </div>

                {nextRuleFields.map((ruleItem, ruleIndex) => (
                  <Form.List key={ruleItem.key} name={[ruleItem.name, 'ruleSentence']}>
                    {(fields, { add, remove }) => (
                      <Expandable defaultExpanded>
                        <ExpandableAttributeItem
                          defaultExpanded
                          title={
                            <DutyRuleTitle name={ruleItem.name} index={ruleIndex} add={add} removeRule={removeRule} />
                          }
                        >
                          <Row gutter={[8, 8]}>
                            {fields.map((item, index) => (
                              <Col key={item.key} xs={24} lg={12}>
                                <DutyFieldItem
                                  key={item.key}
                                  item={item}
                                  index={index}
                                  name={['duty', 'nextRule', ruleItem.name, 'ruleSentence', item.name]}
                                  remove={remove}
                                />
                              </Col>
                            ))}
                          </Row>
                        </ExpandableAttributeItem>
                      </Expandable>
                    )}
                  </Form.List>
                ))}
              </Col>
            );
          }}
        </Form.List>
      </>
    );

    formula = <DutyFormulaList />;
  }

  const title = (
    <Space size='middle'>
      <span>保障责任</span>
      <Switch size='small' checked={enabled} onChange={toggle} />
    </Space>
  );

  return (
    <>
      <FormSection title={title} children={content} />

      {formula}
    </>
  );
}

DutyFields.propTypes = { form: PropTypes.any };

function DutyRuleModal({ onOk, onToggle, index, ...rest }) {
  const { form } = useContext(Context);
  const [ruleForm] = Form.useForm();

  const code = useFormValue(ruleForm, 'ruleCode', (v) => v ?? 'coverage');
  const exists = useFormValue(form, ['duty', 'nextRule'], (v) => getAllRuleValues(v, code, index));
  const options = useFormValue(form, ['duty', code, 'values'], (v) => v ?? []);

  useEffect(() => {
    ruleForm.setFieldsValue({ ruleValue: [] });
  }, [code]);

  const handleToggle = useCall(
    forkHandler(onToggle, (visi) => {
      if (visi) {
        if (index != null) {
          ruleForm.setFieldsValue(form.getFieldValue(['duty', 'nextRule', index]));
        } else {
          ruleForm.resetFields();
        }
      }
    }),
  );

  const handleOk = useCall(async () => {
    const values = await ruleForm.validateFields().catch(catchAndScrollFor(form));
    if (index == null) {
      onOk?.(values);
    } else {
      const formData = form.getFieldsValue();
      set(formData, ['duty', 'nextRule', index, 'ruleCode'])(values.ruleCode);
      set(formData, ['duty', 'nextRule', index, 'ruleValue'])(values.ruleValue);
      form.setFieldsValue(formData);
    }
  });

  const content = (
    <Form form={ruleForm}>
      <FieldCols fields={FIELDS.addDutyRule(exists, options)} form={ruleForm} colProps={{ xs: 12 }} />
    </Form>
  );

  return <ClickModal {...rest} title='责任规则' onToggle={handleToggle} onOk={handleOk} content={content} />;
}

function DutyRuleFields(props) {
  const { form } = useContext(Context);
  const { name, rules, ...colProps } = props;

  return (
    <>
      <FieldCols {...colProps} fields={FIELDS.dutyItem(name)} form={form} />
      {rules?.map((ruleName) => (
        <FieldCols key={ruleName} {...colProps} fields={FIELDS.dutyRule(ruleName, [name])} form={form} />
      )) ?? null}
    </>
  );
}

/** 责任编辑 */
function DutyFieldItem(props) {
  const { form } = useContext(Context);
  const { name, item, index, remove } = props;
  const rules = useFormValue(form, [...name, 'rules']);

  const onRemove = useCall(remove, index);

  return (
    <div className={styles.attrLiabilityItem}>
      <div className={styles.delLine}>
        <div className={styles.title}>附加责任</div>
        <Box grow />
        <PopoverConfirm content='确认删除此附加责任吗?' onOk={onRemove}>
          <Button danger type='link' size='small' icon={<Icon type='close' />} />
        </PopoverConfirm>
      </div>
      <DutyRuleFields name={item.name} rules={rules} colProps={{ xs: 24 }} />
    </div>
  );
}

DutyFieldItem.propTypes = {
  name: PropTypes.any,
  item: PropTypes.any,
  index: PropTypes.number,
  remove: PropTypes.func,
};

export default DutyFields;
